#pragma once
#include <windows.h>
#include <string.h>
#include "WinSystem.hpp"
#include <future>
#include "EventHandle.hpp"
#include "WinSystem.hpp"
#include <iostream>

namespace CppWinApi::Windows
{
    /// @brief 等待异步互斥量参数
    struct WaitAsyncMutexArgs
    {
        /// @brief 输出等待互斥量的状态
        OUT DWORD Status;
        /// @brief 等待失败时，输出错误码
        OUT DWORD ErrorCode;
        /// @brief 需要等待的互斥量
        IN HANDLE Mutex;
        /// @brief 等待的时间
        IN DWORD Milliseconds;
        /// @brief 等待完成事件
        IN HANDLE WaitCompletedEventHandle;
        /// @brief 持有互斥量的线程退出事件
        IN HANDLE CurrentThreadExitEventHandle;
    };

    struct ReleaseAsyncMutexArgs
    {
        /// @brief 需要等待的互斥量
        IN HANDLE Mutex;

        /// @brief 释放互斥量事件
        IN HANDLE ReleaseMutexEventHandle;

        /// @brief 持有互斥量的线程
        IN HANDLE CurrentThreadHandle;

        /// @brief 持有互斥量的线程退出事件
        IN HANDLE CurrentThreadExitEventHandle;
    };

    class CrossProcessMutex
    {
        // 互斥量，本地计算机共享
        HANDLE mMutex;
        // 互斥量释放事件，本地计算机共享
        HANDLE mReleaseMutexEventHandle;
        /// @brief 持有互斥量的线程退出事件
        HANDLE mCurrentThreadExitEventHandle;

        std::string mClassId;

        std::string MakeName(std::string uniqueId, std::string name, bool isGlobal)
        {
            if (isGlobal)
            {
                return std::string("Global\\") + uniqueId + "_" + mClassId + "_" + name;
            }
            else
            {
                return std::string("Local\\") + uniqueId + "_" + mClassId + "_" + name;
            }
        }

        // 创建临时事件（返回 RAII 对象）
        EventHandle CreateTempEvent()
        {
            HANDLE hEvent = CreateEventA(
                nullptr, // 默认安全属性
                TRUE,    // 手动重置事件
                FALSE,   // 初始未触发状态
                nullptr  // 无名事件
            );
            if (hEvent == nullptr)
            {
                throw std::runtime_error("CreateEventA failed: " + std::to_string(GetLastError()));
            }
            return EventHandle(hEvent); // 转移所有权给 RAII 对象
        }

        HANDLE CreateThread(LPTHREAD_START_ROUTINE callback, LPVOID args)
        {
            // HANDLE CreateThread(
            //     LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性，通常为NULL
            //     SIZE_T dwStackSize,                       // 初始堆栈大小，0表示默认
            //     LPTHREAD_START_ROUTINE lpStartAddress,    // 线程函数指针
            //     LPVOID lpParameter,                       // 传递给线程的参数
            //     DWORD dwCreationFlags,                    // 创建标志，0表示立即运行
            //     LPDWORD lpThreadId                        // 接收线程ID，可设为NULL
            // );

            HANDLE hThread = ::CreateThread(
                nullptr,
                0,
                callback,
                args,
                0,
                nullptr);

            if (hThread == NULL)
            {
                throw std::runtime_error("Failed to create thread");
            }

            return hThread;
        }

        void CreateTempThread(LPTHREAD_START_ROUTINE callback, LPVOID args)
        {
            auto handle = this->CreateThread(callback, args);
            ::CloseHandle(handle);
        }

        static DWORD __stdcall WaitAsyncMutexAsync(LPVOID arg)
        {
            std::cout << "[WaitAsyncMutexAsync] Thread started\n";
            std::unique_ptr<WaitAsyncMutexArgs> args(static_cast<WaitAsyncMutexArgs *>(arg));

            // 1、等待持有锁的线程释放互斥量
            auto status = ::WaitForSingleObject(args->Mutex, args->Milliseconds);

            std::cout << "[WaitAsyncMutexAsync] Waiting for mutex (timeout: "
                      << args->Milliseconds << "ms)\n";

            args->Status = status;

            if (status == WAIT_FAILED)
            {
                // 错误直接返回
                args->ErrorCode = GetLastError();
                std::cerr << "[WaitAsyncMutexAsync] Wait failed! Error: "
                          << args->ErrorCode << "\n";
                // 通知调用线程获取锁完成，调用线程通过 ErrorCode 获取错误
                ::SetEvent(args->WaitCompletedEventHandle);
                return 0;
            }

            std::cout << "[WaitAsyncMutexAsync] Mutex acquired. Status: "
                      << (status == WAIT_OBJECT_0 ? "WAIT_OBJECT_0" : "WAIT_TIMEOUT") << "\n";

            // 2、进入  Alertable Wait 状态（可以执行 APC)，等同释放互斥锁的线程通知退出
            // 更可靠的 alertable wait
            auto dwMilliseconds = 0;

            while (true)
            {
                // 确保当前线程已经进入  Alertable Wait 状态，首次肯定是 timeout
                DWORD result = WaitForSingleObjectEx(args->CurrentThreadExitEventHandle, dwMilliseconds, TRUE);

                std::cout << "[WaitAsyncMutexAsync] Alertable wait result: " << result
                          << " (" << (result == WAIT_OBJECT_0 ? "OBJECT" : result == WAIT_IO_COMPLETION ? "APC"
                                                                                                        : "TIMEOUT")
                          << ")\n";

                if (result == WAIT_OBJECT_0 || result == WAIT_IO_COMPLETION)
                {
                    std::cout << "[WaitAsyncMutexAsync] Exit signal received\n";
                    break;
                }

                if (dwMilliseconds == 0)
                {
                    std::cout << "[WaitAsyncMutexAsync] Notifying completion\n";
                    // 通知调用线程已经获取到互斥锁
                    ::SetEvent(args->WaitCompletedEventHandle);
                    dwMilliseconds = 1000;
                }
            }
        }

        static void __stdcall ReleaseCurrentMutex(ULONG_PTR mutex)
        {
            std::cout << "[ReleaseCurrentMutex] From APC to release mutex\n";
            auto handle = (HANDLE)mutex;
            // 1、释放当前持有的互斥量
            ::ReleaseMutex(handle);
        }

        static DWORD __stdcall ReadyToReleaseMutexAsync(LPVOID arg)
        {
            std::cout << "[ReleaseThread] Release thread started\n";
            std::unique_ptr<ReleaseAsyncMutexArgs> args(static_cast<ReleaseAsyncMutexArgs *>(arg));

            std::cout << "[ReleaseThread] Waiting for release signal\n";
            // 1.、等待其他线程呼叫释放事件
            ::WaitForSingleObject(args->ReleaseMutexEventHandle, INFINITE);
            std::cout << "[ReleaseThread] Release signal received\n";

            std::cout << "[ReleaseThread] Queueing APC to owner thread\n";
            // 2、切换回互斥量所有者线程释放互斥量，因为 windows 互斥量只有持有线程才能释放
            ::QueueUserAPC(ReleaseCurrentMutex, args->CurrentThreadHandle, (LONG_PTR)args->Mutex);

            std::cout << "[ReleaseThread] Signaling thread exit\n";
            // 3、通知事件持有者线程退出
            ::SetEvent(args->CurrentThreadExitEventHandle);

            std::cout << "[ReleaseThread] Waiting for owner thread exit\n";
            // 4、等待持有者线程退出
            ::WaitForSingleObject(args->CurrentThreadExitEventHandle, INFINITE);

            std::cout << "[ReleaseThread] Cleaning up thread handle\n";
            // 5、释放持有者线程句柄
            ::CloseHandle(args->CurrentThreadHandle);

            return 0;
        }

    public:
        CrossProcessMutex(std::string uniqueName, bool isGlobal = false) : mClassId("d2e4a1b3-5c6d-4f7a-8b9c-0d1e2f3a4b5c")
        {
            using namespace CppWinApi::Windows::WinSystem;
            mMutex = OpenOrCreateMutex(MakeName(uniqueName, "mutex", isGlobal));
            mReleaseMutexEventHandle = OpenOrCreateEvent(MakeName(uniqueName, "release_mutex_event", isGlobal), true, false);
            mCurrentThreadExitEventHandle = OpenOrCreateEvent(MakeName(uniqueName, "current_thread_exit_event", isGlobal), true, false);
        }

        ~CrossProcessMutex()
        {
            if (mMutex)
                ::CloseHandle(mMutex);
            if (mReleaseMutexEventHandle)
                ::CloseHandle(mReleaseMutexEventHandle);
            if (mCurrentThreadExitEventHandle)
                ::CloseHandle(mCurrentThreadExitEventHandle);
        }

        DWORD Lock(DWORD dwMilliseconds = INFINITE)
        {
            std::cout << "[Lock] Attempting to acquire lock\n";
            auto tempEvent = CreateTempEvent();

            // 在 WaitAsyncMutexAsync 会释放 new WaitAsyncMutexArgs();
            auto waitArgs = new WaitAsyncMutexArgs();
            waitArgs->Mutex = mMutex;
            waitArgs->Milliseconds = dwMilliseconds;
            waitArgs->WaitCompletedEventHandle = tempEvent;
            waitArgs->CurrentThreadExitEventHandle = mCurrentThreadExitEventHandle;

            std::cout << "[Lock] Starting wait thread\n";
            // 1、开启一个异步等待获取互斥锁
            auto currentThreadHandle = this->CreateThread(WaitAsyncMutexAsync, waitArgs);

            std::cout << "[Lock] Waiting for completion signal\n";
            // 2、等待异步线程获取锁完成
            ::WaitForSingleObject(waitArgs->WaitCompletedEventHandle, INFINITE);

            if (waitArgs->Status == WAIT_FAILED)
            {
                std::cerr << "[Lock] Wait failed with error: " << waitArgs->ErrorCode << "\n";
                CloseHandle(currentThreadHandle);
                throw std::system_error(waitArgs->ErrorCode, std::system_category());
            }

            std::cout << "[Lock] Starting release watcher thread\n";

            // 3、开启一个异步线程，等待互斥量的释放
            // 在 ReadyToReleaseMutexAsync 中会释放 new ReleaseAsyncMutexArgs();
            auto releaseArgs = new ReleaseAsyncMutexArgs();
            releaseArgs->CurrentThreadHandle = currentThreadHandle;
            releaseArgs->CurrentThreadExitEventHandle = mCurrentThreadExitEventHandle;
            releaseArgs->Mutex = mMutex;
            releaseArgs->ReleaseMutexEventHandle = mReleaseMutexEventHandle;
            this->CreateTempThread(ReadyToReleaseMutexAsync, releaseArgs);

            std::cout << "[Lock] Lock acquired successfully\n";
            return waitArgs->Status;
        }

        void Unlock()
        {
            std::cout << "[Unlock] Triggering release event\n";
            // 1、引发释放互斥量事件
            ::SetEvent(mReleaseMutexEventHandle);
        }
    };
}